/*
 * RedisConnectPool.h
 *
 *  Created on: 2018年1月29日
 *      Author: cxw
 */

#ifndef REDISCONNECTPOOL_H_
#define REDISCONNECTPOOL_H_

#include "RedisManager.h"

#include <vector>
#include <string>
#include <semaphore.h>
#include <pthread.h>

using namespace std;

class CRedisConnectPool
{
public:
	//redis连接状态
	typedef enum EM_Status
	{
		EM_REDIS_FREE = 0,			//空闲
		EM_REDIS_USE,				//使用中
	}RedisStatus;

	struct ST_Redis
	{
		ST_Redis()
		{
			Clear();
		}

		~ST_Redis()
		{
			Clear();
		}

		bool operator == (const CRedisManager *pRedis)
		{
			return this->pRedis == pRedis;
		}

		void Clear()
		{
			pRedis = NULL;
			redisStatus = EM_REDIS_FREE;
			time = 0;
		}

		CRedisManager* pRedis;
		RedisStatus redisStatus;
		time_t time;
	};

private:
	static CRedisConnectPool *m_pInstance;
	CRedisConnectPool();
public:
	virtual ~CRedisConnectPool();
	static CRedisConnectPool * Instance();

public:
	void SetIpAndPort(const string & strIp, const int & iPort);
	void SetIp(const string & strIp);
	void SetPort(const int & iPort);
	void SetTimeOut(const int & iNum);
	void SetInitConNum(const int & iNum);
	void SetMaxConNum(const int & iNum);
	void SetMinConNum(const int & iNum);

public:
	bool Open();
	void Close();
	CRedisManager* GetRedis();			//获取redis连接
	void ReleaseRedis(CRedisManager* pRedis);					//释放redis连接

private:
	void DeleteTimeOutCon();			//删除过期或者断开连接的redis连接
	int FindRedisCon();					//找寻可用的redis连接
private:
	string m_strIp;
	int m_iPort;
	int m_iTimeOut;			//超时时间(单位：s)

	int m_iInitConNum;		//初始连接数
	int m_iMaxConNum;		//最大连接数
	int m_iMinConNum;		//最小连接数
	int m_iActiveConNum;	//可用连接数

	vector<ST_Redis> m_vstRedis;

	sem_t m_sem;
	pthread_mutex_t *m_pMutex;

	bool m_bOpen;
};

inline void CRedisConnectPool::SetIpAndPort(const string & strIp, const int & iPort )
{
	m_strIp = strIp;
	m_iPort = iPort;
}

inline void CRedisConnectPool::SetIp(const string & strIp)
{
	m_strIp = strIp;
}

inline void CRedisConnectPool::SetPort(const int & iPort)
{
	m_iPort = iPort;
}

inline void CRedisConnectPool::SetTimeOut(const int & iNum)
{
	m_iTimeOut = iNum < 3 ? 3 : iNum;
}

inline void CRedisConnectPool::SetInitConNum(const int & iNum)
{
	m_iInitConNum = iNum < 20 ? 20 : iNum;
}

inline void CRedisConnectPool::SetMaxConNum(const int & iNum)
{
	m_iMaxConNum = iNum < 0 ? 0 : (iNum > 10000 ? 10000 : iNum);
}

inline void CRedisConnectPool::SetMinConNum(const int & iNum)
{
	m_iMinConNum = iNum < 10 ? 10 : iNum ;
}

#endif /* REDISCONNECTPOOL_H_ */
